#include "edge_computing.h"
#include "Logger.h"
#include "utility.h"


void startup(){
    int is=0;
    communicate1();

    //创建用于记录本次启动运行日期时间的文件
    std::ofstream fout_lastrun;
    fout_lastrun.open("lastrun.txt", std::ios_base::out | std::ios_base::app);
    if (fout_lastrun.is_open()) {
        time_t t;
        time(&t);
        fout_lastrun << ctime(&t);
        char *tt=NULL;
        tt=ctime(&t);
        fout_lastrun<<tt;
        fout_lastrun.close();
    } else {
        //若失败，记录失败原因和等级
        char *filename=NULL;
        filename="warmings.log";
        char *content=NULL;
        content="lastrun.txt打开失败\n";
        Logger::instance()->open(filename);
        Logger::instance()->log(Logger::WARN,__FILE__,__LINE__,content);
    }

}

void communicate1(){
    cJSON *one=NULL;
    one=cJSON_CreateObject();
    cJSON_AddNumberToObject(one,"code",1);
    cJSON_AddStringToObject(one,"name","root");
    cJSON_AddStringToObject(one,"password","123456");

    int client_sockfd = 0;
    int len = 0;
    struct sockaddr_in server_addr;
    socklen_t sin_size = 0;
    char *buf= NULL;
    buf=cJSON_Print(one);
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231");
    server_addr.sin_port = htons(9090);

    if((client_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error!(ask1)\n");
    }

    sin_size = sizeof(server_addr/*struct sockaddr_in*/);

    if((len = sendto(client_sockfd, buf, strlen(buf), 0 ,(struct sockaddr*)&server_addr, sizeof(struct sockaddr))) < 0)
    {
        perror("sendto fail!(ask1)\n");
    }
    cout<<inet_ntoa(server_addr.sin_addr)<<endl;
    len = recvfrom(client_sockfd,buf , BUFFSIZE, 0, (struct sockaddr*)&server_addr, &sin_size);
    if(len < 0)
    {
        perror("recvfrom error!(ask1)\n");
        char *filename=NULL;
        filename="warmings.log";
        char *content=NULL;
        content="请求(Edge->Store)未收到应答(Store->Edge)\n";
        Logger::instance()->open(filename);
        Logger::instance()->log(Logger::WARN,__FILE__,__LINE__,content);

    }else{
        cJSON *token=0;
        cJSON *two=NULL;
        two= cJSON_Parse(buf);
        token= cJSON_GetObjectItem(two,"token");
        std::string str_token=token->valuestring;
        cout<<str_token<<endl;

        //用文件存储令牌
        ofstream file_token_temp;
        file_token_temp.open("temp_to_token.txt");
        file_token_temp<<str_token<<endl;
        file_token_temp.close();
    }
    close(client_sockfd);

    cJSON_Delete(one);
    //用消息队列发令牌给collect_data

}



//void set(){
//    Timer timer(1000);
//    timer.on_timer([] {
//        std::cout<<"时间到"<<std::endl;
//    });
//    timer.start();
//
//    std::this_thread::sleep_for(std::chrono::seconds(5));
//    timer.stop();
//
//    std::cout << "Timer count: " << timer.get_count() << std::endl;
//}

void collect_data(){

    //preset detached
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len;
    char buf[1024];

    // create a TCP socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        cerr << "Failed to create socket\n";
        return ;
    }

    // bind to a specific IP address and port
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231"); // bind to a specific IP address
    server_addr.sin_port = htons(23456); // use port in USR-TCP232-304 <Serial Port>
//    client_addr.sin_addr.s_addr = inet_addr("192.168.1.230");
//    client_addr.sin_port = htons(12345);
//    client_addr.sin_addr.s_addr = inet_addr("192.168.1.202");
//    client_addr.sin_port = htons(65300);
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        cerr << "Failed to bind to port\n";
        return ;
    }

    // listen for incoming connections
    if (listen(server_fd, 5) < 0) {
        cerr << "Failed to listen for connections\n";
        return ;
    }

    cout << "Waiting for connections...\n";
    client_addr_len= sizeof(client_addr);
    while (1) {

        // accept a new connection
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);

        //这里才能知道是谁发来的数据，定个函数，用队列or堆栈存发送者的IP消息
        StationTable::pushStationTable(inet_ntoa(client_addr.sin_addr));


        if (client_fd < 0) {
            cerr << "Failed to accept connection\n";
            char *filename=NULL;
            filename="warmings.log";
            char *content=NULL;
            content="Failed to accept connection\n";
            Logger::instance()->open(filename);
            Logger::instance()->log(Logger::WARN,__FILE__,__LINE__,content);
            continue;
        }

        cout << "Accepted connection from " << inet_ntoa(client_addr.sin_addr) << "\n";
        // read data from the client by pthread
        pthread_t pthread_id;
        int ret= pthread_create(&pthread_id,&attr,pthcollect,(void*)(long)client_fd);
        cout << "Closed connection with " << inet_ntoa(client_addr.sin_addr) << "\n";
    }

    close(server_fd);


}

void *pthcollect(void *client_fd){
    char buf[1024];
    int client_fd_=(int)(long)client_fd;
    while(1){

        int n = read(client_fd_, buf, sizeof(buf) - 1);
        if (n < 0) {
            cerr << "Failed to read data from client\n";
            break;
        } else if (n == 0) {
            cout << "Client closed the connection\n";
            break;
        } else {
            buf[n] = '\0';

            cout << "Received data: " << buf << "\n";

            char *filename=NULL;
            filename="infos.log";
            char *content=NULL;
            content=buf;
            Logger::instance()->open(filename);
            Logger::instance()->log(Logger::INFO,__FILE__,__LINE__,content);

            //do something
            send_data(transer(buf));
        }

        close(client_fd_);
    }
}

void send_data(char *buf){
    int server_sockfd = 0;
    int len = 0;
    struct sockaddr_in server_addr;
    int sin_size = 0;
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231");      //("192.168.141.128");
    server_addr.sin_port = htons(9090);

    if((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error!\n");
        char *filename=NULL;
        filename="errors.log";
        char *content=NULL;
        content="Failed to create socket\n";
        Logger::instance()->open(filename);
        Logger::instance()->log(Logger::ERROR,__FILE__,__LINE__,content);
    }

    sin_size = sizeof(struct sockaddr_in);

    if((len = sendto(server_sockfd, buf, strlen(buf), 0 ,(struct sockaddr*)&server_addr, sizeof(struct sockaddr))) < 0)
    {
        perror("sendto fail!\n");
        char *filename=NULL;
        filename="errors.log";
        char *content=NULL;
        content="Failed to send data\n";
        Logger::instance()->open(filename);
        Logger::instance()->log(Logger::ERROR,__FILE__,__LINE__,content);
    }
    close(server_sockfd);

    return;
}

void goodbye(char *token){

    //作废令牌的请求
    cJSON *cjson_ask=NULL;
    cjson_ask=cJSON_CreateObject();
    cJSON_AddNumberToObject(cjson_ask,"code",3);
    char buf_token[16];
    ifstream file_token_temp;
    file_token_temp.open("temp_to_token.txt");
    file_token_temp>>buf_token;
    file_token_temp.close();
    cJSON_AddStringToObject(cjson_ask,"token",buf_token);
    char *buf_ask=NULL;
    buf_ask= cJSON_Print(cjson_ask);
    //发送请求
    int server_sockfd = 0;
    int len = 0;
    struct sockaddr_in server_addr;
    int sin_size = 0;
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231");      //("192.168.141.128");
    server_addr.sin_port = htons(9090);

    if((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error!\n");
        return ;
    }

    sin_size = sizeof(struct sockaddr_in);

    if((len = sendto(server_sockfd, buf_ask, strlen(buf_ask), 0 ,(struct sockaddr*)&server_addr, sizeof(struct sockaddr))) < 0)
    {
        perror("sendto fail!\n");
        return ;
    }
    close(server_sockfd);

}

void communicate_to_Getter(){
    int server_sockfd = 0;
    int len = 0;
    socklen_t sin_size = 0;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    char buf[BUFFSIZE] = {0};

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(9190);

    if((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error!\n");
        return ;
    }

    if(bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("bind error!\n");
        return ;
    }
    sin_size= sizeof(struct sockaddr_in);
    while(1)
    {
        if((len = recvfrom(server_sockfd, buf, BUFFSIZE, 0, (struct sockaddr*)&client_addr, &sin_size)) < 0)
        {
            perror("recvfrom error!\n");
            return ;
        }

        printf("recv from: %s\n",inet_ntoa(client_addr.sin_addr));
        buf[len] = '\0';
        printf("recv is: %s\n",buf);
        if(len <= 0)
        {
            break;
        }
        cJSON *cjson_buf=NULL;
        cjson_buf= cJSON_Parse(buf);
        cJSON *cjson_actionCode=NULL;
        cjson_actionCode= cJSON_GetObjectItem(cjson_buf,"actionCode");
        switch (cjson_actionCode->valueint) {
            case 1:
            {
                //生成json
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",2);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON_AddStringToObject(cjson_respone,"os","银河麒麟");
                cJSON_AddStringToObject(cjson_respone,"version","v10");
//                time_t nowtime;
//                struct tm* p;
//                time(&nowtime);
//                p = localtime(&nowtime);
//                printf("%02d-%02d-%02d\n",1900+p->tm_year,1+p->tm_mon,p->tm_mday);
//                char *t=NULL;
//                char *year=(char*)1900+p->tm_year;
//                char *mon=(char*)1+p->tm_mon;
//                char *mday=(char*)p->tm_mday;
//                char *a=NULL;
//                a=(char*)"-";
//                std::strcat(t,year);
//                std::strcat(t,a);
//                std::strcat(t,mon);
//                std::strcat(t,a);
//                std::strcat(t,mday);

                auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

                //转为字符串
                std::stringstream ss;
                char cc[32]={0};
                // 可以分别以不同的形式进行显示
                //     ss << std::put_time(std::localtime(&t), "%Y-%m-%d-%H-%M-%S");
                ss << std::put_time(std::localtime(&t), "%Y年%m月%d日%H时%M分%S秒");
                //ss << std::put_time(std::localtime(&t), "%Y%m%d%H%M%S");

                std::string str_time = ss.str();
                for(int i=0;i<32;i++){
                    cc[i]=str_time[i];
                }
                cJSON_AddStringToObject(cjson_respone,"lastRun",cc);
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 2)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 5:
            {
                int e=0;
                int w=0;
                int i=0;
                ifstream file1,file2,file3;
                file1.open("errors_count.txt",std::ios_base::out | std::ios_base::app);
                file2.open("warmings_count.txt",std::ios_base::out | std::ios_base::app);
                file3.open("infos_count.log",std::ios_base::out | std::ios_base::app);
                char buf_e={0};
                char buf_w={0};
                char buf_i={0};
                file3>>buf_i;
                i=(int)buf_i;
                file2>>buf_w;
                w=(int)buf_w;
                file1>>buf_e;
                e=(int)buf_e;
                file1.close();
                file2.close();
                file3.close();
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",6);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON_AddNumberToObject(cjson_respone,"dataCount",1);
                cJSON_AddNumberToObject(cjson_respone,"errorCount",e);
                cJSON_AddNumberToObject(cjson_respone,"warningCount",w);
                cJSON_AddNumberToObject(cjson_respone,"infoCount",i);
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 4)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 3:
            {
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",4);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON_AddStringToObject(cjson_respone,"station","等待mac地址编号中");
                cJSON_AddStringToObject(cjson_respone,"name","等待mac地址编号中");
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 6)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 7:
            {
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",8);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON *array=NULL;
                array=cJSON_CreateArray();
                ifstream file;
                file.open("errors.log");
                char errors[1024*64]={0};
                file>>errors;
                file.close();
                cJSON_AddItemToArray(array, cJSON_CreateString(errors));
                cJSON_AddItemToObject(cjson_respone,"logError",array);
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 8)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 9:
            {
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",8);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON *array=NULL;
                array=cJSON_CreateArray();
                ifstream file;
                file.open("warnings.log");
                char errors[1024*64]={0};
                file>>errors;
                file.close();
                cJSON_AddItemToArray(array, cJSON_CreateString(errors));
                cJSON_AddItemToObject(cjson_respone,"logWarning",array);
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 10)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 11:
            {
                cJSON *cjson_respone=NULL;
                cjson_respone=cJSON_CreateObject();
                cJSON_AddNumberToObject(cjson_respone,"action",8);
                cJSON_AddNumberToObject(cjson_respone,"success",1);
                cJSON *array=NULL;
                array=cJSON_CreateArray();
                ifstream file;
                file.open("warnings.log");
                char errors[1024*64]={0};
                file>>errors;
                file.close();
                cJSON_AddItemToArray(array, cJSON_CreateString(errors));
                cJSON_AddItemToObject(cjson_respone,"logInfo",array);
                char *buf_respone=NULL;
                buf_respone= cJSON_Print(cjson_respone);
                if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                          (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                    perror("sendto error(communicate to getter code 12)\n");
                }
                cJSON_Delete(cjson_respone);
            }
            case 13:
            {
                cJSON *cjson_order=NULL;
                cjson_order= cJSON_GetObjectItem(cjson_buf,"order");
                cJSON *cjson_password=NULL;
                cjson_password= cJSON_GetObjectItem(cjson_buf,"password");
                if(!std::strcmp(cjson_buf->valuestring,"123456")){
                    std::perror("getter密码错误");
                    char *buf_respone=NULL;
                    buf_respone=(char *)"getter密码错误";
                    if(sendto(server_sockfd, buf_respone, strlen(buf_respone), 0 ,
                              (struct sockaddr*)&client_addr, sizeof(struct sockaddr)) < 0){
                        perror("sendto error(communicate to getter code 12)\n");
                    }
                }else{
                    if(std::strcmp(cjson_order->valuestring,"start")){
                        std::cout<<"正在和getter通讯"<<std::endl;
                    }else if(std::strcmp(cjson_order->valuestring,"close")){
                        std::cout<<"断开与getter通讯\n";
                        break;
                    }
                }
            }
        }
    }
    close(server_sockfd);
}

void write_log(char *filename,char *content){
    int errors_count=0;
    int warnings_count=0;
    int infos_count=0;
    Logger::instance()->open(filename);
    if(0==strcmp(filename,"errors.log")) {
        errors_count++;
        Logger::instance()->log(Logger::ERROR,__FILE__,__LINE__,content);
    }
    else if (strcmp(filename,"warmings.log")==0) {
        warnings_count++;
        Logger::instance()->log(Logger::WARN,__FILE__,__LINE__,content);
    }
    else if(strcmp(filename,"infos.log")==0){
        infos_count++;
        Logger::instance()->log(Logger::INFO,__FILE__,__LINE__,content);
    }
    ofstream file1,file2,file3;
    file1.open("errors_count.txt",std::ios_base::out | std::ios_base::app);
    file2.open("warmings_count.txt",std::ios_base::out | std::ios_base::app);
    file3.open("infos_count.log",std::ios_base::out | std::ios_base::app);
    file1<<errors_count<<endl;
    file2<<warnings_count<<endl;
    file3<<infos_count<<endl;
    file1.close();
    file2.close();
    file3.close();
}



void file_clear(){
//    std::ofstream fout_errors, fout_warmings, fout_infos;
//    fout_errors.open("errors.log");
//    fout_warmings.open("warmings.log");
//    fout_infos.open("infos.log");
    ofstream file1,file2,file3;
    file1.open("errors_count.txt");
    file2.open("warmings_count.txt");
    file3.open("infos_count.log");
    file1<<"新一轮的记录\n";
    file2<<"新一轮的记录\n";
    file3<<"新一轮的记录\n";
    file1.close();
    file2.close();
    file3.close();
}
//每从气象站收一次数据算一轮，存储系统和数据监控也是假设这个样子

